package websocketserver

import (
	"encoding/json"
	"fmt"
	"gitee.com/jamon/espoir_go/common"
	"gitee.com/jamon/espoir_go/global"
	"gitee.com/jamon/espoir_go/logger"
	"gitee.com/jamon/espoir_go/route"
	"gitee.com/jamon/espoir_go/rpcserver"
	"github.com/gorilla/websocket"
	"net/http"
	"sync"
)

var upgrade = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
}

type Manager struct {
	quitOnce sync.Once

	sessionMgr *global.SessionManager
	routeCtl   *route.Controller

	rpcHandler *rpcserver.RequestHandler
	config     *global.Config
}

func NewManager() (mgr *Manager, err error) {
	mgr = &Manager{
		sessionMgr: global.GetSessionManager(),
		routeCtl:   route.GetController(),
		config:     global.GetNodeData().Config,
	}

	mgr.rpcHandler, err = rpcserver.NewRequestHandler()
	return
}

func (mgr *Manager) InitWebsocketServer() (err error) {
	webconf := global.GetNodeData().Config.WebSocket
	addr := fmt.Sprintf("%s:%d", webconf.Host, webconf.Port)
	logger.Debug("InitWebsocketServer: ", logger.Kwargs{"addr": addr})
	http.HandleFunc("/ws", mgr.HandleMsg)
	err = http.ListenAndServe(addr, nil)
	if err != nil {
		logger.Error("initWebsocketServer: ", logger.Kwargs{"err": err})
		return err
	}
	logger.Debug("InitWebsocketServer start: ", logger.Kwargs{"addr": addr})

	return
}

func (mgr *Manager) HandleMsg(w http.ResponseWriter, r *http.Request) {
	conn, err := upgrade.Upgrade(w, r, nil)
	if err != nil {
		logger.Error("HandleMsg: ", logger.Kwargs{"err": err})
		return
	}
	defer func(conn *websocket.Conn) {
		err := conn.Close()
		if err != nil {

		}
	}(conn)

	// session_id在切换网络时会复用老的session_id，所以此处退出时暂不清除session_id
	sessionID, err := mgr.sessionMgr.AddWebsocketSession(conn)
	if err != nil {
		return
	}

	for {
		_, msg, err := conn.ReadMessage()
		if err != nil {
			logger.Warn("HandleMsg: read failed", logger.Kwargs{"err": err})
			return
		}
		logger.Debug("HandleMsg: ", logger.Kwargs{"msg": string(msg)})
		decodeMsg := &common.MsgRequest{}
		err = json.Unmarshal(msg, decodeMsg)
		if err != nil {
			logger.Error("HandleMsg: ", logger.Kwargs{"err": err})
			continue
		}
		decodeMsg.Type = common.MsgType_REQUEST
		decodeMsg.SessionID = sessionID
		err = mgr.realHandleMsg(decodeMsg)
		if err != nil {
			logger.Error("HandleMsg: ", logger.Kwargs{"err": err})
			continue
		}
	}
}

func (mgr *Manager) realHandleMsg(msg *common.MsgRequest) (err error) {
	// 新连接三种情况：1. 用户首次连接； 2. 断线重连； 3. 切网后重连（如wifi了移动网络）

	if msg.MsgId == common.DefaultInnerMsgIDs.SwitchNetMsgID {
		// 切网后重连, 沿用原来的session_id
		var data common.SwitchNetRequest
		err := json.Unmarshal(msg.Data, &data)
		if err != nil {
			logger.Error("realHandleMsg: ", logger.Kwargs{"err": err})
			return err
		}
		if mgr.sessionMgr.IsSessionValid(data.SessionID, data.Token) {
			//TODO: session_id有效, 切换成功，更新通道，断开旧的连接
			logger.Debug("realHandleMsg: switch success")

		} else {
			// session_id无效, 切换失败
			logger.Error("realHandleMsg: switch failed ", logger.Kwargs{"err": err})
		}
	} else {
		// 非切换网络消息，进行转发
		res := common.MsgResponse{Seq: msg.Seq, MsgId: msg.MsgId}
		err := mgr.rpcHandler.HandleMsg(msg, &res)
		if err != nil {
			logger.Error("realHandleMsg: ", logger.Kwargs{"err": err})
			return err
		}
		logger.Debug("realHandleMsg: ", logger.Kwargs{"msgId": msg.MsgId, "res": string(res.Data)})
		err = mgr.sessionMgr.SendMsg(msg.SessionID, &res)
		if err != nil {
			return err
		}
	}
	return
}

func (mgr *Manager) Close() {
	mgr.quitOnce.Do(func() {
		// TODO: close websocket server
	})
}
